<?php

namespace App\Services;

use App\Common\Libs\DingTalk;
use App\Common\Libs\StringHelper;
use App\Consts\DingTalkConst;
use App\Consts\GlobalConst;
use Illuminate\Support\Facades\Log;

/**
 * 钉钉推送服务
 * Class DingService
 * @package App\Services
 */
class DingService extends BaseService
{

    /**
     * 入队列 - 发送钉钉消息
     * @param $params
     * @return mixed
     */
    public function sendDingMsg($params)
    {
        $taskId = $taskId = service()->PushService->getTaskId();
        $channelId = $params['channel_id'];
        $platform = $params['platform'];
        $scene = $params['scene'];
        $mobileList = !empty($params['mobile_list']) ? $params['mobile_list'] : '';
        $userIdList = !empty($params['userid_list']) ? $params['userid_list'] : '';
        $msg = $params['msg'];
        // 填充默认值
        $params['code'] = '';
        $params['template'] = !empty($params['template']) ? $params['template'] : '';
        $params['msg_type'] = !empty($params['msg_type']) ? $params['msg_type'] : DingTalkConst::DINGTALK_MSG_NOTICE_TYPE_WORK;

        // 获取场景值
        if (!empty($params['scene_id'])) {
            $sceneInfo = $this->MsgSceneService->getSceneInfo($params['scene_id']);
            $sceneInfo['scene_id'] = $sceneInfo['id'];
        } else {
            $sceneInfo = $this->MsgSceneService->getScene($scene, $platform, $channelId);
        }
        $params['platform_id']= $sceneInfo['platform_id'];
        $params['scene_id'] = $sceneInfo['scene_id'];

        // 查询用户信息，多个用户插入多条记录，但是taskID相同
        if (!empty($mobileList)){
            // 通过手机号发送
            $mobileAry = explode(',', $mobileList);
            // replace config
            $config = $this->MsgSceneService->getDingTalkType(['msg_type' => $params['msg_type']]);
            if ($config) {
                $mobileAry = array_merge($mobileAry, array_column($config['common_user'], 'mobile'));
            }
            $mobileAry = array_unique($mobileAry);
            foreach ($mobileAry as $mobile) {
                $params['mobile'] = $mobile;
                $user = $this->UserService->getUser($mobile);
                // 不存在的用户先跳过
                if (empty($user)) {
                    $info = "[RMQ][API][PUBLISHER][ERROR]" . " [".$taskId."][-1] User Empty - " . json_encode([
                            'mobile' => $mobile,
                            'request' => $params,
                        ]) . PHP_EOL;
                    Log::info($info);
                    //continue;
                }
                $identity = StringHelper::encode('m_' . $mobile);
                $msgContent = $this->getMsgContent($config, $msg, $params['msg_type'], $identity);
                // 获取推送信息
                $body = $this->RabbitMQService->getFormatBody(GlobalConst::RMQ_QUEUE_TYPE_DINGTALK,
                    'sendDingMsgCallback',
                    ['mobile_list' => $mobile, 'userid_list' => '', 'msg' => $msgContent],
                    $taskId
                );
                // 发送推送数据
                $this->PushService->sendData($params, $taskId, $user, $body);
            }
        } else {
            // 通过钉钉用户ID发送
            $dingUserIdAry = explode(',', $userIdList);
            // replace config
            $config = $this->MsgSceneService->getDingTalkType(['msg_type' => $params['msg_type']]);
            if ($config) {
                $dingUserIdAry = array_merge($dingUserIdAry, array_column($config['common_user'], 'ding_user_id'));
            }
            $dingUserIdAry = array_unique($dingUserIdAry);
            foreach ($dingUserIdAry as $dingUserId) {
                $params['mobile'] = '';
                $user = $this->UserService->getUserByDingUserId($dingUserId);
                // 不存在的用户先跳过
                if (empty($user)) {
                    $info = "[RMQ][API][PUBLISHER][ERROR]" . " [".$taskId."][-2] User Empty - " . json_encode([
                            'mobile' => '',
                            'ding_user_id' => $dingUserId,
                            'request' => $params,
                        ]) . PHP_EOL;
                    Log::info($info);
                    //continue;
                }
                $identity = StringHelper::encode('d_' . $dingUserId);
                $msgContent = $this->getMsgContent($config, $msg, $params['msg_type'], $identity);
                // 获取推送信息
                $body = $this->RabbitMQService->getFormatBody(GlobalConst::RMQ_QUEUE_TYPE_DINGTALK,
                    'sendDingMsgCallback',
                    ['mobile_list' => '', 'userid_list' => $dingUserId, 'msg' => $msgContent],
                    $taskId
                );
                // 发送推送数据
                $this->PushService->sendData($params, $taskId, $user, $body);
            }
        }

        // 返回任务ID
        return ['task_id' => $taskId];
    }

    /**
     * get message content
     * @param $config
     * @param $msg
     * @param $type
     * @param $identity
     * @return array|mixed
     */
    protected function getMsgContent($config, $msg, $type, $identity)
    {
        if ($config) {
            $msg = is_array($msg) ? $msg : (json_decode($msg, true) ? : []);
            if (isset($msg['preview'])) {
                $flag = false === strpos($msg['preview'], '?') ? '?' : '&';
                $msg['preview'] = $msg['preview'] . $flag . "_d={$identity}&_u=" . uniqid();
            }
            // 工单消息参数变更
            if (in_array($type, [
                DingTalkConst::DINGTALK_MSG_TYPE_IT_DEMAND_NOTICE,
                DingTalkConst::DINGTALK_MSG_TYPE_IT_DEMAND_NOTICE_TEST,
                DingTalkConst::DINGTALK_MSG_TYPE_IT_DEMAND_NOTICE_CHECK,
            ])) {
                // 已提测，人员需要更改
                if ($type == DingTalkConst::DINGTALK_MSG_TYPE_IT_DEMAND_NOTICE_TEST) {
                    $user = end($config['common_user']);
                    $msg['officer'] = getVal($user, 'real_name');
                }
            }
            $msg = vsprintf(json_encode($config['content']), $msg);
            $msg = json_decode($msg, true);
        }
        return $msg;
    }

    /**
     * 回调 - 发送钉钉工作通知
     * @param $body
     * @return mixed
     */
    public function sendDingMsgCallback($body)
    {
        $data = $body['data'];
        if (isset($data['msg'])) {
            $data['msg'] = is_array($data['msg']) ? json_encode($data['msg']) : $data['msg'];
        }
        $messageId = !empty($body['message_id']) ? $body['message_id'] : 0;
        $this->validate($data, [
            'msg' => 'required|json',
            'mobile_list' => 'max:9999',
            'userid_list' => 'max:9999',
        ]);
        $msg = json_decode($data['msg'], true);
        $mobileList = $data['mobile_list'];
        $userIdList = $data['userid_list'];
        $ding = DingTalk::getInstance();
        $res = $ding->send($msg, $mobileList, $userIdList);
        $pushInfo = $ding->request();
        // @example {"errcode":0,"errmsg":"ok","task_id":376148906258,"request_id":"4mwmi631iznh"}
        $res = json_decode($res, true) ? : [];
        // 此处不能用 empty 判断，恰巧 errcode 为 0
        $success = isset($res['errcode']) && 0 == $res['errcode'];

        // 返回数据到服务
        return $this->PushService->receiveData($messageId, $success, $res, $pushInfo);
    }

}